// 遍历 Array 可以采用下标循环, 遍历 Map 和 Set 就无法使用下标
// 为了统一集合类型, ES6 标准引入了新的 iterable 类型, Array、Map 和 Set 都属于 iterable 类型
// 具有 iterable 类型的集合可以通过新的 for ... of 循环来遍历
// for ... of 循环是 ES6 引入的新的语法, 请测试你的浏览器是否支持
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { console.log(x); }
for (var x of s) { console.log(x); }
for (var x of m) { console.log(x[0] + ' = ' + x[1]); }

// for ... in 循环由于历史遗留问题, 它遍历的实际上是对象的属性名称
// 一个Array数组实际上也是一个对象, 它的每个元素的索引被视为一个属性
// 当我们手动给 Array 对象添加了额外的属性后, for ... in 循环将带来意想不到的意外效果
var a = ['A', 'B', 'C'];
a.name = 'Hello';
console.log(a.length);  // 3
for (var x in a) { console.log(x); }  // '0', '1', '2', 'name'  // for ... in 循环将把 name 包括在内, 但 Array 的 length 属性却不包括在内
for (var x of a) { console.log(x); }  // 'A', 'B', 'C'

// 然而, 更好的方式是直接使用 iterable 内置的 forEach 方法, 它接收一个函数, 每次迭代就自动回调该函数
a.forEach(function (element, index, array) {  // element: 指向当前元素的值, index: 指向当前索引, array: 指向Array对象本身
    console.log(element);
    console.log(index);
    console.log(array);
});
